﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace LowLevelGraphics.Filter
{
    /// <summary>
    /// Two step thresholding.
    /// All color channel components are calculated by checking for a given range
    /// and then a logical and operation is applied.
    /// </summary>
    public class Threshold3 : Threshold
    {
        protected bool m_bOr = false;
        protected byte rMin = 10;
        protected byte gMin = 10;
        protected byte bMin = 10;

        protected byte rMax = 90;
        protected byte gMax = 90;
        protected byte bMax = 90;

        /// <summary>
        /// Default constructor
        /// </summary>
        public Threshold3()
        {
        }

        /// <summary>
        /// Specify min and max threshold
        /// </summary>
        /// <param name="_colorMin"></param>
        /// <param name="_colorMax"></param>
        public Threshold3(Color _colorMin, Color _colorMax)
            : this(_colorMin.R, _colorMin.G, _colorMin.B, _colorMax.R, _colorMax.G,_colorMax.B)
        {
        }

        /// <summary>
        /// specify min and max thresholds for each channel
        /// </summary>
        /// <param name="_rMin"></param>
        /// <param name="_gMin"></param>
        /// <param name="_bMin"></param>
        /// <param name="_rMax"></param>
        /// <param name="_gMax"></param>
        /// <param name="_bMax"></param>
        public Threshold3(byte _rMin, byte _gMin, byte _bMin, byte _rMax, byte _gMax, byte _bMax)
        {
            rMin = _rMin;
            gMin = _gMin;
            bMin = _bMin;

            rMax = _rMax;
            gMax = _gMax;
            bMax = _bMax;
        }

        /// <summary>
        /// Gets or sets or
        /// </summary>
        public bool OR
        {
            get { return m_bOr; }
            set { m_bOr = value; }
        }

        /// <summary>
        /// Gets or sets the R min.
        /// </summary>
        /// <value>The R min.</value>
        public byte RMin
        {
            get { return rMin; }
            set { rMin = value; }
        }

        /// <summary>
        /// Gets or sets the G min.
        /// </summary>
        /// <value>The G min.</value>
        public byte GMin
        {
            get { return gMin; }
            set { gMin = value; }
        }

        /// <summary>
        /// Gets or sets the B min.
        /// </summary>
        /// <value>The B min.</value>
        public byte BMin
        {
            get { return bMin; }
            set { bMin = value; }
        }

        /// <summary>
        /// Gets or sets the R max.
        /// </summary>
        /// <value>The R max.</value>
        public byte RMax
        {
            get { return rMax; }
            set { rMax = value; }
        }

        /// <summary>
        /// Gets or sets the G max.
        /// </summary>
        /// <value>The G max.</value>
        public byte GMax
        {
            get { return gMax; }
            set { gMax = value; }
        }

        /// <summary>
        /// Gets or sets the B max.
        /// </summary>
        /// <value>The B max.</value>
        public byte BMax
        {
            get { return bMax; }
            set { bMax = value; }
        }

        /// <summary>
        /// Gets or sets the color of the min.
        /// </summary>
        /// <value>The color of the min.</value>
        public Color MinColor
        {
            get { return Color.FromArgb(rMin, gMin, bMin); }
            set
            {
                rMin = value.R; gMin = value.G; bMin = value.B;
            }
        }

        /// <summary>
        /// Gets or sets the color of the max.
        /// </summary>
        /// <value>The color of the max.</value>
        public Color MaxColor
        {
            get { return Color.FromArgb(rMax, gMax, bMax); }
            set
            {
                rMax = value.R; gMax = value.G; bMax = value.B;
            }
        }
        /// <summary>
        /// used by clone to create a deep copy
        /// </summary>
        /// <param name="_threshold3"></param>
        internal Threshold3(Threshold3 _threshold3)
        {
            this.rMin = _threshold3.rMin;
            this.gMin = _threshold3.gMin;
            this.bMin = _threshold3.bMin;
            
            this.rMax = _threshold3.rMax;
            this.gMax = _threshold3.gMax;
            this.bMax = _threshold3.bMax;

            this.m_bOr = _threshold3.m_bOr;
        }

        /// <summary>
        /// Executes this filter
        /// </summary>
        /// <param name="_bitmap"></param>
        /// <returns></returns>
        public override UnsafeBitmap Execute(UnsafeBitmap _bitmap)
        {
            UnsafeBitmap bitmap = _bitmap;

            int nHeight = bitmap.Height;
            int nWidth = bitmap.Width;

            Color color = Color.Transparent;
            Color colorBackground = m_ColorBackground;
            Color colorForeground = m_ColorForeground;
            Color colorToSet = Color.Transparent;

            int y = 0;
            int x = 0;
            for (y = 0; y < nHeight; y++)
            {
                for (x = 0; x < nWidth; x++)
                {
                    color = bitmap.GetPixel(x, y);
                    if (m_bOr)
                    {
                        if ((rMax >= color.R && color.R > rMin)
                              || (gMax >= color.G && color.G > gMin)
                              || (bMax >= color.B && color.B > bMin))
                        {
                            colorToSet = colorBackground;
                        }
                        else
                        {
                            colorToSet = colorForeground;
                        }
                    }
                    else
                    {
                        if ((rMax >= color.R && color.R > rMin)
                              && (gMax >= color.G && color.G > gMin)
                              && (bMax >= color.B && color.B > bMin))
                        {
                            colorToSet = colorBackground;
                        }
                        else
                        {
                            colorToSet = colorForeground;
                        }
                    }
                    bitmap.SetPixel(x, y, colorToSet);
                }
            }
            return _bitmap;
        }

        /// <summary>
        /// used to create a deep copy
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            return new Threshold3(this);
        }
    }
}
